package com.zlfund.cat.demo;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Build;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

/**
 * Created by chenj
 * Created on 2017/7/31
 */

public class DownloadProgress extends View {
    private int mMaxProgress = 100;
    private int mCurrentProgress;
    private Paint mCurrentProgressPaint, mStrokePaint;
    private int mWidth;
    private int mHeight;
    private int mStrokeWidth;
    private int mRealWidth;
    private int mRealHeight;
    private float mForeGroundWaveWidth = 1.5f;
    private Path mPath;
    private RectF mLeftRectF;
    private RectF mRightRectF;
    private Path mDownloadPath;
    private ObjectAnimator mDownloadProgressAnim, mRunProgressAnim1, mRunProgressAnim2, mRunProgressAnim3;
    private float mCurrentWidth;
    private double mForeGroundParam;
    private float mCurWidth;
    private double mSecondParam;
    private float mSecondWidth = 1f;
    private float mThirdWidth = 0.8f;
    private double mThirdParam;
    private int mPointDistrict;
    private float mCurWidth2;
    private float mCurWidth3;
    private float mRadius1,mRadius2,mRadius3;

    public DownloadProgress(Context context) {
        this(context, null);
    }

    public DownloadProgress(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DownloadProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPath = new Path();
        mDownloadPath = new Path();
        mLeftRectF = new RectF();
        mRightRectF = new RectF();
        mCurrentProgressPaint = new Paint();
        mStrokePaint = new Paint();
        mStrokeWidth = 4;
        mStrokePaint = initPaint(Color.LTGRAY, mStrokeWidth, Paint.Style.STROKE);
        mCurrentProgressPaint = initPaint(Color.rgb(0xcc,0x9d,0x3e), mStrokeWidth, Paint.Style.FILL);
        mDownloadProgressAnim = new ObjectAnimator();
        mRunProgressAnim1 = initAnimator(2000,"CurWidth");
        mRunProgressAnim2 = initAnimator(2000,"CurWidth2");
        mRunProgressAnim3 = initAnimator(2000,"CurWidth3");
        mDownloadProgressAnim.setTarget(this);
        mDownloadProgressAnim.setDuration(100);
        mDownloadProgressAnim.setPropertyName("CurrentProgress");
        mDownloadProgressAnim.setInterpolator(new LinearInterpolator());
        mRadius1 = 10f;
        mRadius2 = 8f;
        mRadius3 = 12f;
    }

    private ObjectAnimator initAnimator(long duration,String propertyName){
        ObjectAnimator anim = new ObjectAnimator();
        anim.setTarget(this);
        anim.setDuration(duration);
        anim.setPropertyName(propertyName);
        anim.setInterpolator(new LinearInterpolator());
        anim.setRepeatMode(ValueAnimator.RESTART);
        anim.setRepeatCount(ValueAnimator.INFINITE);
        return anim;
    }

    private Paint initPaint(int color, int strokeWidth, Paint.Style style) {
        Paint paint = new Paint();
        paint.setColor(color);
        paint.setStrokeWidth(strokeWidth);
        paint.setAntiAlias(true);
        paint.setStyle(style);
        return paint;
    }

    public void startAnimDelay(final ObjectAnimator anim, long delay){
        postDelayed(new Runnable() {
            @Override
            public void run() {
                anim.start();
            }
        },delay);
    }

    private boolean mSecondPointShow = false;
    private boolean mThirdPointShow = false;
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mWidth == 0) {
            mWidth = getWidth();
            mHeight = getHeight();
            mRealWidth = mWidth - mStrokeWidth * 2;
            mRealHeight = mHeight - mStrokeWidth * 2;
            mCurrentWidth = mRealHeight / 2;
            mForeGroundParam = 2 * mForeGroundWaveWidth * Math.PI / mWidth;
            mSecondParam = 2 * mSecondWidth * Math.PI / mWidth;
            mThirdParam = 2 * mThirdWidth * Math.PI / mWidth;
            mRunProgressAnim1.setFloatValues(mRealWidth - mRealHeight / 2, 0);
            mRunProgressAnim2.setFloatValues(mRealWidth - mRealHeight / 2, 0);
            mRunProgressAnim3.setFloatValues(mRealWidth - mRealHeight / 2, 0);
            startAnimDelay(mRunProgressAnim1,0);
            startAnimDelay(mRunProgressAnim2,700);
            startAnimDelay(mRunProgressAnim3,1400);
            mPointDistrict = (mRealWidth - mRealHeight / 2) / 3;
        }
        mPath.reset();
        mDownloadPath.reset();
        mLeftRectF.set(mStrokeWidth, mStrokeWidth, mHeight - mStrokeWidth, mHeight - mStrokeWidth);
        mRightRectF.set(mWidth - mHeight + mStrokeWidth, mStrokeWidth, mWidth - mStrokeWidth, mHeight - mStrokeWidth);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            mPath.moveTo(mHeight / 2, mStrokeWidth);
            mPath.arcTo(mLeftRectF, 270, -180, false);
            mPath.lineTo(mWidth - mHeight / 2, mHeight - mStrokeWidth);
            mPath.arcTo(mRightRectF, 90, -180, false);
            mPath.lineTo(mHeight / 2, mStrokeWidth);
        } else {
            mPath.addRoundRect(mStrokeWidth, mStrokeWidth, mRealWidth + mStrokeWidth, mRealHeight + mStrokeWidth, mRealHeight / 2, mRealHeight / 2, Path.Direction.CW);
        }

        if (mMaxProgress == 0) {
            mDownloadPath.moveTo(mHeight / 2, mStrokeWidth);
            mDownloadPath.arcTo(mLeftRectF, 270, -180, false);
            mDownloadPath.close();
        } else {
            if (mCurrentProgress == mMaxProgress){
                mDownloadPath.moveTo(mHeight / 2, mStrokeWidth);
                mDownloadPath.arcTo(mLeftRectF, 270, -180, false);
                mDownloadPath.lineTo(mWidth - mHeight / 2, mHeight - mStrokeWidth);
                mDownloadPath.arcTo(mRightRectF, 90, -180, false);
                mDownloadPath.lineTo(mHeight / 2, mStrokeWidth);
            }else {
                mDownloadPath.moveTo(mHeight / 2, mStrokeWidth);
                mDownloadPath.arcTo(mLeftRectF, 270, -180, false);
                mDownloadPath.lineTo(mCurrentWidth, mHeight - mStrokeWidth);
                mDownloadPath.lineTo(mCurrentWidth, mStrokeWidth);
                mDownloadPath.close();
            }
        }
        canvas.drawPath(mPath, mStrokePaint);
        canvas.drawPath(mDownloadPath, mCurrentProgressPaint);
        if (!mRunProgressAnim1.isRunning()) return;
        if (mMaxProgress != 0 && mMaxProgress == mCurrentProgress) {
            mRunProgressAnim1.end();
            mRunProgressAnim2.end();
            mRunProgressAnim3.end();
            return;
        }

        float x = mCurWidth + mRealHeight / 2;
        canvas.drawCircle(x, getSinHeight(mRealWidth - mRealHeight / 2 - mCurWidth,mForeGroundParam,0.5f), mRadius1, mCurrentProgressPaint);

        if (!mRunProgressAnim2.isRunning())return;
        float x2 = mCurWidth2 + mRealHeight / 2;
        canvas.drawCircle(x2, getSinHeight(mRealWidth - mRealHeight / 2 - mCurWidth2,mSecondParam,0.3f), mRadius2, mCurrentProgressPaint);

        if (!mRunProgressAnim3.isRunning())return;
        float x3 = mCurWidth3 + mRealHeight / 2;
        canvas.drawCircle(x3, getSinHeight(mRealWidth - mRealHeight / 2 - mCurWidth3,mThirdParam,0.4f), mRadius3, mCurrentProgressPaint);

//        if (mSecondPointShow) {
//            if (x < mRealWidth - mPointDistrict){
//                canvas.drawCircle(x + mPointDistrict, getSinHeight(mRealWidth - mRealHeight / 2 - mCurWidth + mPointDistrict,mThirdParam), 6f, mCurrentProgressPaint);
//            }else {
//                canvas.drawCircle(x - 2 * mPointDistrict, getSinHeight(mRealWidth - mRealHeight / 2 - mCurWidth - 2 * mPointDistrict,mThirdParam), 6f, mCurrentProgressPaint);
//            }
//        }else {
//            if (x < mRealWidth - mPointDistrict){
//                canvas.drawCircle(x + mPointDistrict, getSinHeight(mRealWidth - mRealHeight / 2 - mCurWidth + mPointDistrict,mThirdParam), 6f, mCurrentProgressPaint);
//                mSecondPointShow = true;
//            }
//        }
//        if (mThirdPointShow){
//            if (x < mRealWidth - 2 * mPointDistrict){
//                canvas.drawCircle(x + 2 * mPointDistrict, getSinHeight(- mRealWidth + mRealHeight / 2 + mCurWidth,mSecondParam), 8f, mCurrentProgressPaint);
//            }else {
//                canvas.drawCircle(x - mPointDistrict, getSinHeight(- mRealWidth + mRealHeight / 2 + mCurWidth - mPointDistrict,mSecondParam), 8f, mCurrentProgressPaint);
//            }
//        }else {
//            if (x < mRealWidth - 2 * mPointDistrict){
//                canvas.drawCircle(x + 2 * mPointDistrict, getSinHeight(- mRealWidth + mRealHeight / 2 + mCurWidth + 2 * mPointDistrict,mSecondParam), 8f, mCurrentProgressPaint);
//                mThirdPointShow = true;
//            }
//        }
    }

    private float getSinHeight(double ang,double param,float top) {
        return mHeight * 0.5f - (float) (mHeight * top * Math.sin(ang * param));
    }

    private int mPreProgress;
    public void setProgress(int progress) {
        if (mPreProgress == progress) return;
        mDownloadProgressAnim.setIntValues(mPreProgress,progress);
        mDownloadProgressAnim.start();
        mPreProgress = progress;
    }

    public void setCurrentProgress(int progress){
        mCurrentProgress = progress;
        if (mMaxProgress != 0 && progress == mMaxProgress)
            mCurrentWidth = mRealWidth - mRealHeight / 2;
        mCurrentWidth = progress * 1.0f / mMaxProgress * (mRealWidth - mRealHeight) + mRealHeight / 2;
        postInvalidate();
    }

    public int getCurrentProgress() {
        return mCurrentProgress;
    }

    public void setCurWidth(float width) {
        mCurWidth = width;
        float multi = 0;
        if (mCurWidth + mRealHeight / 2 > mCurrentWidth)
            multi = 1.5f - mCurWidth / (mRealWidth - mRealHeight / 2);
        mRadius1 = multi * 10;
        postInvalidate();
    }

    public float getCurWidth() {
        return mCurWidth;
    }

    public void setCurWidth2(float width) {
        mCurWidth2 = width;
        float multi = 0;
        if (mCurWidth2 + mRealHeight / 2 > mCurrentWidth)
            multi = 1.5f - mCurWidth2 / (mRealWidth - mRealHeight / 2);
        mRadius2 = multi * 8;
        postInvalidate();
    }

    public float getCurWidth2() {
        return mCurWidth2;
    }

    public void setCurWidth3(float width) {
        mCurWidth3 = width;
        float multi = 0;
        if (mCurWidth3 + mRealHeight / 2 > mCurrentWidth)
            multi = 1.5f - mCurWidth3 / (mRealWidth - mRealHeight / 2);
        mRadius3 = multi * 12;
        postInvalidate();
    }

    public float getCurWidth3() {
        return mCurWidth3;
    }
}
